/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2009, 2010.

	This file is part of Maxsi Engine.

	Maxsi Engine is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi engine is distributed in the hope that it will be useful, but WITHOUT
	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
	for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Engine. If not, see <http://www.gnu.org/licenses/>.

	MaxsiEngine.dll
	A general purpose C++ library for the Maxsi Technology Project.

	MaxsiComplex.cpp
	IMAGINARY FUNCTIONS!

******************************************************************************/

#include "MaxsiEngine.h"

BeginMaxsiNamespace

#define A (Real)
#define B (Imaginary)
#define C (Oprand.Real)
#define D (Oprand.Imaginary)

ComplexDouble::ComplexDouble()
{
	A		=	0.0f;
	B		=	0.0f;
}

ComplexDouble::ComplexDouble(double Reality)
{
	A		=	Reality;
	B		=	0.0f;
}

ComplexDouble::ComplexDouble(double Reality, double Imagination)
{
	A		=	Reality;
	B		=	Imagination;
}

bool	ComplexDouble::operator==	(const ComplexDouble& Oprand)
{
	return (Real == Oprand.Real) && (Imaginary == Oprand.Imaginary);
}

bool	ComplexDouble::operator!=	(const ComplexDouble& Oprand)
{
	return (Real != Oprand.Real) || (Imaginary != Oprand.Imaginary);		
}


ComplexDouble&		ComplexDouble::operator=	(const ComplexDouble& Oprand)
{
	A		=	C;
	B		=	D;
	return (*this);
}

ComplexDouble&		ComplexDouble::operator-=	(const ComplexDouble& Oprand)
{
	A		-=	C;
	B		-=	D;
	return (*this);
}

ComplexDouble&		ComplexDouble::operator+=	(const ComplexDouble& Oprand)
{
	A		+=	C;
	B		+=	D;
	return (*this);
}

ComplexDouble&		ComplexDouble::operator*=	(const ComplexDouble& Oprand)
{
	// (A+Bi)*(C+Di) = AC+ADi+CBi+BiDi = (AC-BD) + i(AD+BC) where i = Sqrt(-1)

	double	OldA	=	A;
	double	OldC	=	C;

	A		=	(A*C) - (B*D);
	B		=	(OldA*D) + (B*OldC);

	return (*this);
}

ComplexDouble&		ComplexDouble::operator/=	(const ComplexDouble& Oprand)
{
	// (A+Bi)/(C+Di)

	double	OldA	=	A;
	double	OldC	=	C;

	A		=	(A*C+B*D)/(C*C+D*D);
	B		=	(B*C-OldA*D)/(OldC*OldC+D*D);
	return (*this);
}

ComplexDouble&		ComplexDouble::operator+	(const ComplexDouble& Oprand)
{
	A		+=	C;
	B		+=	D;
	return (*this);
}

ComplexDouble&		ComplexDouble::operator-	(const ComplexDouble& Oprand)
{
	A		-=	C;
	B	-=	D;
	return (*this);
}

ComplexDouble&		ComplexDouble::operator*	(const ComplexDouble& Oprand)
{
	// (A+Bi)*(C+Di) = AC+ADi+CBi+BiDi = (AC-BD) + i(AD+BC) where i = Sqrt(-1)

	double	OldA	=	A;
	double	OldC	=	C;

	A		=	(A*C) - (B*D);
	B		=	(OldA*D) + (B*OldC);

	return (*this);
}

ComplexDouble&		ComplexDouble::operator/	(const ComplexDouble& Oprand)
{
	// (A+Bi)/(C+Di)

	double	OldA	=	A;
	double	OldC	=	C;

	A		=	(A*C+B*D)/(C*C+D*D);
	B		=	(B*C-OldA*D)/(OldC*OldC+D*D);
	return (*this);
}



ComplexFloat::ComplexFloat()
{
	A		=	0.0f;
	B		=	0.0f;
}

ComplexFloat::ComplexFloat(float Reality)
{
	A		=	Reality;
	B		=	0.0f;
}

ComplexFloat::ComplexFloat(float Reality, float Imagination)
{
	A		=	Reality;
	B		=	Imagination;
}

bool	ComplexFloat::operator==	(const ComplexFloat& Oprand)
{
	return (Real == Oprand.Real) && (Imaginary == Oprand.Imaginary);
}

bool	ComplexFloat::operator!=	(const ComplexFloat& Oprand)
{
	return (Real != Oprand.Real) || (Imaginary != Oprand.Imaginary);		
}


ComplexFloat&		ComplexFloat::operator=	(const ComplexFloat& Oprand)
{
	A		=	C;
	B		=	D;
	return (*this);
}

ComplexFloat&		ComplexFloat::operator-=	(const ComplexFloat& Oprand)
{
	A		-=	C;
	B		-=	D;
	return (*this);
}

ComplexFloat&		ComplexFloat::operator+=	(const ComplexFloat& Oprand)
{
	A		+=	C;
	B		+=	D;
	return (*this);
}

ComplexFloat&		ComplexFloat::operator*=	(const ComplexFloat& Oprand)
{
	// (A+Bi)*(C+Di) = AC+ADi+CBi+BiDi = (AC-BD) + i(AD+BC) where i = Sqrt(-1)

	float	OldA	=	A;
	float	OldC	=	C;

	A		=	(A*C) - (B*D);
	B		=	(OldA*D) + (B*OldC);

	return (*this);
}

ComplexFloat&		ComplexFloat::operator/=	(const ComplexFloat& Oprand)
{
	// (A+Bi)/(C+Di)

	float	OldA	=	A;
	float	OldC	=	C;

	A		=	(A*C+B*D)/(C*C+D*D);
	B		=	(B*C-OldA*D)/(OldC*OldC+D*D);
	return (*this);
}

ComplexFloat&		ComplexFloat::operator+	(const ComplexFloat& Oprand)
{
	A		+=	C;
	B		+=	D;
	return (*this);
}

ComplexFloat&		ComplexFloat::operator-	(const ComplexFloat& Oprand)
{
	A		-=	C;
	B	-=	D;
	return (*this);
}

ComplexFloat&		ComplexFloat::operator*	(const ComplexFloat& Oprand)
{
	// (A+Bi)*(C+Di) = AC+ADi+CBi+BiDi = (AC-BD) + i(AD+BC) where i = Sqrt(-1)

	float	OldA	=	A;
	float	OldC	=	C;

	A		=	(A*C) - (B*D);
	B		=	(OldA*D) + (B*OldC);

	return (*this);
}

ComplexFloat&		ComplexFloat::operator/	(const ComplexFloat& Oprand)
{
	// (A+Bi)/(C+Di)

	float	OldA	=	A;
	float	OldC	=	C;

	A		=	(A*C+B*D)/(C*C+D*D);
	B		=	(B*C-OldA*D)/(OldC*OldC+D*D);
	return (*this);
}

EndMaxsiNamespace
